#include<stdio.h>
#include<stdlib.h>
#include <string>
#include "bdcloud.h"
#include "mygpio.h"

#include "input/camera_input.h"
#include "input/camera_manager.h"
#include "surface.h"

#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>

#include <securec.h>

using namespace std;
using namespace OHOS;
using namespace OHOS::CameraStandard;


// 拍照临时目录存放
std::string g_strPictureLocation = "/data/temp_capture.jpg";

// 我的所有车牌
std::string g_strMyCars[2]={"粤B376541", "湘F78953"};

// 闪灯，暂时用于模拟门岗识别后的结果
int flashLed(int gpio){
    for (int i=0;i<=3;i++){
        gpio_write(gpio, 1);
        usleep(3000000);
        gpio_write(gpio, 0);
        usleep(1000000);
    }
    return 0;
}


enum class mode_ {
    MODE_PREVIEW = 0,
    MODE_PHOTO
};


// 保存图片到指定路径
static int32_t SaveYUV(mode_ mode, const char *buffer, int32_t size)
{
    static const std::int32_t FILE_PERMISSION_FLAG = 00766;
    char path[PATH_MAX] = {0};
    int32_t retVal;

    if (mode == mode_::MODE_PREVIEW) {
        //system("mkdir -p /data/preview");
        retVal = sprintf_s(path, sizeof(path) / sizeof(path[0]), "/data/temp_preview.yuv");
    } else {
        //system("mkdir -p /data/capture");
        retVal = sprintf_s(path, sizeof(path) / sizeof(path[0]), g_strPictureLocation.c_str());
    }
    if (retVal < 0) {
        printf("Path Assignment failed");
        return -1;
    }
    printf("%s, saving file to %s\n", __FUNCTION__, path);
    int imgFd = open(path, O_RDWR | O_CREAT, FILE_PERMISSION_FLAG);
    if (imgFd == -1) {
        printf("%s, open file failed, errno = %s.", __FUNCTION__, strerror(errno));
        return -1;
    }
    int ret = write(imgFd, buffer, size);
    if (ret == -1) {
        printf("%s, write file failed, error = %s.", __FUNCTION__, strerror(errno));
        close(imgFd);
        return -1;
    }
    close(imgFd);
    return 0;
}

// 1.创建缓冲区消费者端监听器（CaptureSurfaceListener）以保存图像。
class CaptureSurfaceListener : public IBufferConsumerListener {
public:
    mode_ mode;
    sptr<Surface> surface_;

    void OnBufferAvailable() override
    {
        int32_t flushFence = 0;
        int64_t timestamp = 0;
        OHOS::Rect damage; // initialize the damage

        OHOS::sptr<OHOS::SurfaceBuffer> buffer = nullptr;
        surface_->AcquireBuffer(buffer, flushFence, timestamp, damage);
        if (buffer != nullptr) {
            char *addr = static_cast<char *>(buffer->GetVirAddr());
            int32_t size = buffer->GetSize();

            // Save the buffer(addr) to a file.
            SaveYUV(mode, addr, size);

            surface_->ReleaseBuffer(buffer, -1);
        }
    }
};




int main()
{
    int gpio_fd, ret;
    struct pollfd fds[1];
    char buff[10];

    //hi3516 gpio口:41为红灯, 28为底板红灯（19为绿灯好像跟相机冲突？） 1为1号按键
    gpio_unexport(41);
    gpio_unexport(28);
    gpio_unexport(1);
 
    gpio_export(41);
    gpio_export(28);
    gpio_direction(41, 1);//output out
    gpio_direction(28, 1);//output out
    // gpio_direction(41, 1);//output out
    //gpio_write(19, 1);

    
    //1按钮初始化
    gpio_export(1);
    gpio_direction(1, 0);//input in
    gpio_edge(1,2);
    gpio_fd = open("/sys/class/gpio/gpio1/value",O_RDONLY);
    if(gpio_fd < 0)
    {
        MSG("Failed to open value!\n");  
        return -1;  
    }
    fds[0].fd = gpio_fd;
    fds[0].events  = POLLPRI;




  // 参考Camera组件拍摄 https://gitee.com/openharmony/multimedia_camera_standard
    // 样例:foundation/multimedia/camera_standard/interfaces/innerkits/native/test/camera_capture.cpp

    // 2.获取相机管理器实例并获取相机对象列表。
    int32_t intResult = -1;
    sptr<CameraManager> camManagerObj = CameraManager::GetInstance();
    std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras();
    if (cameraObjList.size() < 0) {
        printf("No Camera existed! Return -1!");
        return -1;
    }
    for (auto& it : cameraObjList) {
        printf("Camera ID: %s\n", it->GetID().c_str());
    }

    //3. 创建采集会话。
    sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession();
    if (captureSession == nullptr) {
        printf("Failed to create capture session");
        return -1;
    }
    //4. 开始配置采集会话。
    captureSession->BeginConfig();

    //5. 使用相机对象创建相机输入。
    sptr<CaptureOutput> photoOutput;
    sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]);
    if (cameraInput != nullptr) {
        //6.将相机输入添加到采集会话。
        intResult = captureSession->AddInput(cameraInput);
        if (intResult == 0) {
            //7.创建消费者Surface并注册监听器以监听缓冲区更新。拍照的宽和高可以配置为所支持的 1280x960 分辨率。
            sptr<Surface> photoSurface = Surface::CreateSurfaceAsConsumer();
            photoSurface->SetDefaultWidthAndHeight(1280, 960);
            sptr<CaptureSurfaceListener> capturelistener = new CaptureSurfaceListener();
            capturelistener->mode = mode_::MODE_PHOTO;
            capturelistener->surface_ = photoSurface;
            photoSurface->RegisterConsumerListener((sptr<IBufferConsumerListener> &)capturelistener);

            //8.使用上面创建的 Surface 创建拍照输出。
            photoOutput = camManagerObj->CreatePhotoOutput(photoSurface);
            if (photoOutput == nullptr) {
                printf("Failed to create PhotoOutput");
                return -1;
            }
            //9.将拍照输出添加到采集会话。
            intResult = captureSession->AddOutput(photoOutput);
            if (intResult != 0) {
                printf("Failed to Add output to session, intResult: %d", intResult);
                return -1;
            }
            //10. 将配置提交到采集会话。
            intResult = captureSession->CommitConfig();
            if (intResult != 0) {
                printf("Failed to Commit config, intResult: %d", intResult);
                return -1;
            }

        }
    }


    BdCloud bdCloud;
    setlocale(LC_ALL, "zh_CN.UTF-8");   
    
    while(1)
    {

        ret = poll(fds,1,5000);
        if( ret == -1 )
        MSG("poll\n");
        if( fds[0].revents & POLLPRI)
        {
            ret = lseek(gpio_fd,0,SEEK_SET);
            if( ret == -1 )
               MSG("lseek\n");

            ret = read(gpio_fd,buff,10);//读取按钮值，但这里没使用
            if( ret == -1 )
               MSG("read\n");


            //11.拍摄照片。
            intResult = ((sptr<PhotoOutput> &)photoOutput)->Capture();
            if (intResult != 0) {
                printf("Failed to capture, intResult: %d\n", intResult);
                return -1;
            }else{
                printf("Success to capture, intResult: %d\n", intResult);
            }

            string strToken;
            string strText;
            bool isMyCar = false;

            CURLcode nRes = bdCloud.getToken(strToken);

            if (nRes == CURLE_OK){
                printf("Success to getToken = %s\n" , strToken.c_str());
            }else{
                printf("Fail to getToken result = %d\n",nRes);
            }
            nRes = bdCloud.recognizeText(g_strPictureLocation, strText , strToken);

            if (nRes == CURLE_OK){
                
                printf("Success to recognizeText = %s\n" , strText.c_str());
                std::string x = "HelloWorld";
                for (int i = 0; i <= sizeof(g_strMyCars) / sizeof(g_strMyCars[0]); i++){
                    if (g_strMyCars[i].compare(strText) == 0 ){
                        printf("This is my car %s\n", strText.c_str());
                        flashLed(28); //识别正确车牌，闪绿灯
                        isMyCar = true;
                        break;
                    }
                }

                // if (x.compare(strText) == 0 ){
                //     printf("HelloWorld\n");
                // }
                
                // x = "粤B376541";
                // if (x.compare(strText) == 0 ){
                //     printf("粤B376541\n");
                // }

            }else{
                     
                printf("Fail to recognizeText result = %d\n",nRes );
            }

            if (!isMyCar){
                flashLed(41); // 未识别，闪红灯
            }

        
            //gpio_write(44, cnt++%2);
            printf("**********************************\n");
        }
        printf("one loop\n");
        //usleep(5);
    }



    // BdCloud bdCloud;

    // //string strURL = "http://81.71.17.188:8080/distschedule-api/user/phone/13480796892";
    // //string strURL = "http://14.215.177.39";
    // //string strURL = "http://www.baidu.com";
    // string strToken;
    // string strText;
    // //CURLcode nRes = bdCloud.httpGet(strURL, strResponse,300);

    // //CURLcode nRes = bdCloud.recognizeText("", strResponse);
    // CURLcode nRes = bdCloud.getToken(strToken);

    // //size_t nSrcLength = strResponse.length();

    // if (nRes == CURLE_OK){
    //     printf("Success to getToken = %s\n" , strToken.c_str());
    // }else{
    //     printf("Fail to getToken result = %d\n",nRes);
    //     return 0;
    // }

    // nRes = bdCloud.recognizeText("/data/2.png" , strText , strToken);

    // if (nRes == CURLE_OK){
    //     printf("Success to recognizeText = %s\n" , strText.c_str());
    // }else{
    //      setlocale(LC_ALL, "zh_CN.UTF-8");        
    //     printf("Fail to recognizeText result = %d\n",nRes );
    //     return 0;
    // }

    //12. 释放采集会话资源。
    captureSession->Release();

    printf("\n zzz end http\n");

    return 0;
}